package com.user.annotation.aspect;


import com.user.annotation.AccessLimit;
import com.user.config.Exception.ServiceException;
import com.user.util.impl.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.rmi.ServerException;

/**
 * @program: Member_Perks_Store
 * @description: 接口限流切面类
 * @author: 无恙
 * @create: 2024-06-18 08:15
 **/

@Aspect
@Component
@Slf4j
@Scope
public class AccessLimitAspect {

    @Autowired
    private RedisUtil redisUtil;

    @Around("within(@org.springframework.web.bind.annotation.RestController *) && @annotation(limit)")
    public Object requestLimit(ProceedingJoinPoint joinPoint, AccessLimit limit) throws ServiceException {
        // 继续执行目标方法
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ip = request.getRemoteAddr();
            String redisKey = ip + ":" + request.getRequestURI();


            // 在 Redis 中递增计数
            Long requestCount = redisUtil.incr(redisKey, 1);

            // 第一次访问时设置键的过期时间
            if (requestCount == 1) {
                redisUtil.expire(redisKey, limit.time());
            }


            // 检查是否超过访问限制
            if (requestCount > limit.count()) {
                log.error("IP {} 请求次数过多，异常", ip);
                throw new ServerException("请求次数过多，异常！");
            }
            return joinPoint.proceed();
        } catch (Throwable ex) {
            throw new ServiceException(200,"请求次数过多，异常！"); // Handle other exceptions
        }
    }

}
